//
//  YNetUtils.swift
//  EasyEverything
//
//  Created by YangZhe on 17/1/23.
//  Copyright © 2017年 kuletech. All rights reserved.
//
extension YUIViewController{
    open func yDisplay(imageView:UIImageView,url:String){
        if url.isEmpty {
            if YConfig.isSetPicDefault && YConfig.loadingFailImage != nil {
                imageView.contentMode = .scaleAspectFit
                imageView.image = UIImage(named:YConfig.loadingFailImage!)
            }
        }else{
            if YConfig.isSetPicDefault && YConfig.loadingImage != nil {
                imageView.image = UIImage(named:YConfig.loadingImage!)
            }
            YImageLoader.sharedLoader.imageForUrl(urlString: url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) { (image, url) in
                if image != nil {
                    imageView.image = image
                }else{
                    if YConfig.isSetPicDefault && YConfig.loadingFailImage != nil {
                        imageView.contentMode = .scaleAspectFit
                        imageView.image = UIImage(named:YConfig.loadingFailImage!)
                    }
                }
            }
        }
    }
    
    open func yDisplay(button:UIButton,url:String){
        if url.isEmpty {
            if YConfig.isSetPicDefault && YConfig.loadingFailImage != nil {
                button.setImage(UIImage(named:YConfig.loadingFailImage!), for: .normal)
                button.imageView!.contentMode = .scaleAspectFit
            }
        } else {
            if YConfig.isSetPicDefault && YConfig.loadingImage != nil {
                button.setImage(UIImage(named:YConfig.loadingImage!), for: .normal)
            }
            YImageLoader.sharedLoader.imageForUrl(urlString: url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!) { (image, url) in
                if image != nil {
                    button.setImage(image, for: .normal)
                }else{
                    if YConfig.isSetPicDefault && YConfig.loadingFailImage != nil {
                        button.setImage(UIImage(named:YConfig.loadingFailImage!), for: .normal)
                        button.imageView!.contentMode = .scaleAspectFit
                    }
                }
            }
        }
    }
    
    open func yIsConnectionAvailable() -> Bool{
        return Reachability()!.isReachableViaWiFi || Reachability()!.isReachableViaWWAN
    }
    
    open func yPost <T:NSObject>(ip:String = YConfig.IP,_  jkid:String,_ kv: YJsonKV?,httpMethod:String = "POST",_ callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?) -> ()){
        yPost(ip: ip, jkid: jkid, kv: kv,httpMethod:httpMethod, callBack: callBack, showProgress: true , showErrorToast: true)
    }
    
    open func yPost <T:NSObject>(ip:String = YConfig.IP, jkid:String, kv: YJsonKV?,httpMethod:String = "POST", callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?) -> (),showProgress:Bool = true, showErrorToast:Bool = true){
        guard
            !TextUtils.isEmpty(YConfig.IP)
            else {
                yPrint("yPost工具ip缺失，请配置YConfig或传入ip")
                self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                return
        }
        guard
            yIsConnectionAvailable()
            else {
                yShowAlertController(alertView: UIAlertController(title: nil, message: "网络不可用，请检查网络！！！", preferredStyle: .alert), hasCancelAction: false, alertActions:
                    UIAlertAction(title: "重试", style: .default, handler: { (_) in
                        self.yPost(ip:ip, jkid: jkid, kv: kv,httpMethod:httpMethod, callBack: callBack, showProgress: showProgress, showErrorToast: showErrorToast)
                }))
                self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                return
        }
        if showProgress {
            self.yShowLoadingProgress()
        }
        let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
        session.dataTask(with: YAppDelegate.getRequestByRequest(viewController: self,ip:ip,jkid: jkid,inputJsonKV: kv,httpMethod: httpMethod) , completionHandler: { (resultData, response , error) -> Void in
            self.yRunOnUIThread {
                guard
                    self.isAlive
                    else {
                        return
                }
                
                if showProgress {
                    self.yDismissLoadingProgress()
                }

                guard
                    error == nil
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                        if showErrorToast {
                            self.yToast(YConfig.DEBUG ? "网络请求异常！！！\(error!.localizedDescription)" : "网络请求错误，请重试")
                        }
                        self.yPrint("\(jkid):responseFailure:网络请求异常！！！\(error!.localizedDescription)")
                        return
                }
                
                guard
                    let data = resultData
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                        let message = YConfig.DEBUG ? "网络请求响应为空" : "网络请求错误，请重试"
                        if showErrorToast {
                            self.yToast(message)
                        }
                        self.yPrint("\(jkid):responseFailure:\(message)")
                        return
                }
                
                guard
                    let responseTempStr = YConfig.encryptParamsAble ? YAESCrypt.decrypt(String(data: data,encoding:.utf8), password: YConfig.encryptParamsKey) : String(data: data,encoding:.utf8)
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                        let message = YConfig.DEBUG ? "网络请求响应转码失败" : "网络请求错误，请重试"
                        if showErrorToast {
                            self.yToast(message)
                        }
                        self.yPrint("\(jkid):responseFailure:\(message)")
                        return
                }
                
                let responseStr = responseTempStr.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "\t", with: " ").replacingOccurrences(of: "\r ", with: " ")
                self.yPrint("\(jkid):requestSuccess:\(responseStr)")
                guard
                    !TextUtils.isEmpty(responseStr)
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                        if showErrorToast {
                            self.yToast(YConfig.DEBUG ? "网络请求响应为空" : "网络请求错误，请重试")
                        }
                        return
                }
                
                let root = try? (JSONSerialization.jsonObject(with: (YConfig.compressParamsAble ? responseStr.data(using: .utf8)?.gunzipped() : responseStr.data(using: .utf8))!, options:.allowFragments) as! NSDictionary)["root"] as! NSDictionary
                
                guard
                    root != nil
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: nil, callBack: callBack)
                        if showErrorToast {
                            self.yToast(YConfig.DEBUG ? "网络请求回执message解析异常，响应字符串：\n\(responseStr)" : "网络请求错误，请重试")
                        }
                        return
                }
                
                let code = root!["code"] as? String
                
                guard
                    code == "1"
                    else{
                        self.doCallBack_old(isSuccess: false,results: [T](),code: code, callBack: callBack)
                        if showErrorToast {
                            if let message = root!["message"] as? String{
                                self.yToast(YConfig.DEBUG ?"网络请求回执message:\n\(message)" :message)
                            }else{
                                self.yToast(YConfig.DEBUG ?"网络请求回执message解析异常，响应字符串:\n\(responseStr)" :"网络请求错误，请重试")
                            }
                        }
                        return
                }
                
                guard
                    let results = root!["result"] as? NSArray
                    else{
                        self.doCallBack_old(isSuccess: true, results: [T](),code: code, callBack: callBack)
                        return
                }
                
                if T() is NSDictionary {
                    var resultTArray = [T]()
                    for result in results{
                        resultTArray.append(result as! T)
                    }
                    self.doCallBack_old(isSuccess: true,results: resultTArray,code: code, callBack: callBack)
                } else {
                    var resultTArray = [T]()
                    for result in results{
                        resultTArray.append(T.mj_object(withKeyValues: result))
                    }
                    self.doCallBack_old(isSuccess: true,results: resultTArray,code: code, callBack: callBack)
                }
            }
        }).resume()
    }
    
    func doCallBack_old <T:NSObject>(isSuccess:Bool, results:[T], code:String?, callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?) -> ()){
        let _ = self.yRunOnUIThreadDelay(delay: 0.01, block: {
            callBack(isSuccess, results, code)
        })
    }
    
    //```````````````````````````
    open func yPost <T:NSObject>(ip:String = YConfig.IP,_  jkid:String,_ kv: YJsonKV?,httpMethod:String = "POST",_ callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?,_ msg:String?) -> ()){
        yPost(ip: ip, jkid: jkid, kv: kv,httpMethod:httpMethod, callBack: callBack, showProgress: true , showErrorToast: true)
    }
    
    open func yPost <T:NSObject>(ip:String = YConfig.IP, jkid:String, kv: YJsonKV?,httpMethod:String = "POST", callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?,_ msg:String?) -> (),showProgress:Bool = true, showErrorToast:Bool = true){
        guard
            !TextUtils.isEmpty(YConfig.IP)
            else {
                yPrint("yPost工具ip缺失，请配置YConfig或传入ip")
                self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: "yPost工具ip缺失，请配置YConfig或传入ip", callBack: callBack)
                return
        }
        guard
            yIsConnectionAvailable()
            else {
                yShowAlertController(alertView: UIAlertController(title: nil, message: "网络不可用，请检查网络！！！", preferredStyle: .alert), hasCancelAction: false, alertActions:
                    UIAlertAction(title: "重试", style: .default, handler: { (_) in
                        self.yPost(ip:ip, jkid: jkid, kv: kv,httpMethod:httpMethod, callBack: callBack, showProgress: showProgress, showErrorToast: showErrorToast)
                    }))
                self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: "网络不可用，请检查网络！！！", callBack: callBack)
                return
        }
        if showProgress {
            self.yShowLoadingProgress()
        }
        let session = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: OperationQueue.main)
        session.dataTask(with: YAppDelegate.getRequestByRequest(viewController: self,ip:ip,jkid: jkid,inputJsonKV: kv,httpMethod: httpMethod) , completionHandler: { (resultData, response , error) -> Void in
            self.yRunOnUIThread {
                guard
                    self.isAlive
                    else {
                        return
                }
                
                if showProgress {
                    self.yDismissLoadingProgress()
                }
                
                guard
                    error == nil
                    else{
                        self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: YConfig.DEBUG ? "网络请求异常！！！\(error!.localizedDescription)" : "网络请求错误，请重试", callBack: callBack)
                        if showErrorToast {
                            self.yToast(YConfig.DEBUG ? "网络请求异常！！！\(error!.localizedDescription)" : "网络请求错误，请重试")
                        }
                        self.yPrint("\(jkid):responseFailure:网络请求异常！！！\(error!.localizedDescription)")
                        return
                }
                
                guard
                    let data = resultData
                    else{
                        let message = YConfig.DEBUG ? "网络请求响应为空" : "网络请求错误，请重试"
                        self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: message, callBack: callBack)
                        if showErrorToast {
                            self.yToast(message)
                        }
                        self.yPrint("\(jkid):responseFailure:\(message)")
                        return
                }
                
                guard
                    let responseTempStr = YConfig.encryptParamsAble ? YAESCrypt.decrypt(String(data: data,encoding:.utf8), password: YConfig.encryptParamsKey) : String(data: data,encoding:.utf8)
                    else{
                        let message = YConfig.DEBUG ? "网络请求响应转码失败" : "网络请求错误，请重试"
                        self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: message ,callBack: callBack)
                        if showErrorToast {
                            self.yToast(message)
                        }
                        self.yPrint("\(jkid):responseFailure:\(message)")
                        return
                }
                
                let responseStr = responseTempStr.replacingOccurrences(of: "\n", with: " ").replacingOccurrences(of: "\t", with: " ").replacingOccurrences(of: "\r ", with: " ")
                self.yPrint("\(jkid):requestSuccess:\(responseStr)")
                guard
                    !TextUtils.isEmpty(responseStr)
                    else{
                        let message = YConfig.DEBUG ? "网络请求响应为空" : "网络请求错误，请重试"
                        self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: message, callBack: callBack)
                        if showErrorToast {
                            self.yToast(message)
                        }
                        return
                }
                
                let root = try? (JSONSerialization.jsonObject(with: (YConfig.compressParamsAble ? responseStr.data(using: .utf8)?.gunzipped() : responseStr.data(using: .utf8))!, options:.allowFragments) as! NSDictionary)["root"] as? NSDictionary
                
                guard
                    root != nil
                    else{
                        let message = YConfig.DEBUG ? "网络请求回执message解析异常，响应字符串：\n\(responseStr)" : "网络请求错误，请重试"
                        self.doCallBack(isSuccess: false,results: [T](),code: nil,msg: message, callBack: callBack)
                        if showErrorToast {
                            self.yToast(message)
                        }
                        return
                }
                
                let code = root!["code"] as? String
                
                guard
                    code == "1"
                    else{
                        var message = ""
                        if let msg = root!["message"] as? String{
                            message = YConfig.DEBUG ?"网络请求回执message:\n\(msg)" :msg
                        }else{
                            message = YConfig.DEBUG ?"网络请求回执message解析异常，响应字符串:\n\(responseStr)" :"网络请求错误，请重试"
                        }
                        self.doCallBack(isSuccess: false,results: [T](),code: code,msg: message, callBack: callBack)
                        if showErrorToast {
                            self.yToast(message)
                        }
                        return
                }
                
                guard
                    let results = root!["result"] as? NSArray
                    else{
                        self.doCallBack(isSuccess: true, results: [T](),code: code,msg: YConfig.DEBUG ?"网络请求回执result解析异常，响应字符串:\n\(responseStr)" :"网络请求错误，请重试", callBack: callBack)
                        return
                }
                
                if T() is NSDictionary {
                    var resultTArray = [T]()
                    for result in results{
                        resultTArray.append(result as! T)
                    }
                    self.doCallBack(isSuccess: true,results: resultTArray,code: code,msg: nil, callBack: callBack)
                } else {
                    var resultTArray = [T]()
                    for result in results{
                        resultTArray.append(T.mj_object(withKeyValues: result))
                    }
                    self.doCallBack(isSuccess: true,results: resultTArray,code: code,msg: nil, callBack: callBack)
                }
            }
        }).resume()
    }
    
    func doCallBack <T:NSObject>(isSuccess:Bool, results:[T], code:String?, msg:String?, callBack: @escaping (_ isSuccess:Bool,_ results:[T], _ code:String?,_ msg:String?) -> ()){
        let _ = self.yRunOnUIThreadDelay(delay: 0.01, block: {
            callBack(isSuccess, results, code, msg)
        })
    }
    
    public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
            completionHandler(URLSession.AuthChallengeDisposition.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
        }
    }
}
